﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System;
using System.IO.Ports;
using System.Net;
using System.Net.NetworkInformation;

namespace PowerTestController.Communication
{
    public class ITECH_SCPI_Communication
    {
        #region 命令常量
        /// <summary>
        /// 测试
        /// </summary>
        private const string TEST = "*IDN?";
        /// <summary>
        /// 设置电流值
        /// </summary>
        private const string SET_CURRENT = "CURRent ";
        /// <summary>
        /// 设置电压设置值
        /// </summary>
        private const string GET_CURRENT_SET = "FETCh:CURRent?";
        /// <summary>
        /// 获取电源输出电流
        /// </summary>
        private const string GET_CURRENT = "MEASure:CURRent?";
        /// <summary>
        /// 设置电压值
        /// </summary>
        private const string SET_VOLTAGE = "VOLTage ";
        /// <summary>
        /// 设置电压设置值
        /// </summary>
        private const string GET_VOLTAGE_SET = "FETCh:VOLTage?";
        /// <summary>
        /// 获取电源输出电压
        /// </summary>
        private const string GET_VOLTAGE = "MEASure:VOLTage?";
        /// <summary>
        /// 获取最新测量值（电压、电流、功率）
        /// </summary>
        private const string GET_MEASure = "MEASure?";
        /// <summary>
        /// 打开输出
        /// </summary>
        private const string OPEN_OUTPUT_CURRENT = "OUTPut ON";
        /// <summary>
        /// 关闭输出
        /// </summary>
        private const string CLOSE_OUTPUT_CURRENT = "OUTPut OFF";
        /// <summary>
        /// 查询输出状态
        /// 返回0|1 0表示OFF，1表示ON
        /// </summary>
        private const string GET_OUTPUT_STATUS = "OUTPut?";
        /// <summary>
        /// 恒流模式
        /// </summary>
        private const string CONSTANT_CURRENT = "CC:PRIority HIGH";
        /// <summary>
        /// 获取电源模式
        /// </summary>
        private const string GET_PRIORITY_TYPE = "PRIority:TYPE?";
        /// <summary>
        /// 程序控制模式
        /// </summary>
        private const string PROCESS_CTRL = "SYSTem:REMote";
        /// <summary>
        /// 本地控制模式
        /// </summary>
        private const string LOCAL_CTRL = "SYSTem:LOCal";
        #endregion

        private TcpClient? client;
        private NetworkStream? stream;
        private StreamWriter? writer;
        private StreamReader? reader;
        public ITECH_SCPI_Communication()
        {

        }
        public string? Open(string ipAddress, int port)
        {
            string? mes = "";
            try
            {
                mes = CheckIPAndConnect(ipAddress);
                if (mes!=null)
                {
                    return mes;
                }
                client = new TcpClient();
                client?.Connect(ipAddress, port);
                stream = client?.GetStream();
                writer = new StreamWriter(stream!);
                reader = new StreamReader(stream!);
                return null;
            }
            catch (Exception ex)
            {
                mes = $"设备无法打开，请检查: {ex.Message}";
                return mes;
            }
        }

        /// <summary>
        /// 检查IP并判断是否连通
        /// </summary>
        /// <param name="ipAddress">IP地址</param>
        /// <returns></returns>
        public string CheckIPAndConnect(string ipAddress)
        {
            if (!IsValidIPAddress(ipAddress))
            {
                return "输入的不是有效的 IP 地址";
            }
            if (!Ping(ipAddress))
            {
                return "IP地址通讯连接失败";
            }
            return null;
        }

        /// <summary>
        /// 判断是否文本符合ipv4地址格式
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        static bool IsValidIPAddress(string ipAddress) => IPAddress.TryParse(ipAddress, out _);

        /// <summary>
        /// ping
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool Ping(string ip)
        {
            try
            {
                Ping ping = new Ping();
                PingReply pingReply = ping.Send(ip, 700);
                return pingReply.Status == IPStatus.Success;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        /// <summary>
        /// 获取当前连接状态
        /// </summary>
        /// <returns></returns>
        public bool GetIsOpen()
        {
            if (client != null)
            {
                return client.Connected;
            }
            return false;
        }

        // 发送 SCPI 命令并接收响应
        public string SendCommand(string command)
        {
            try
            {
                // 发送命令
                writer!.WriteLine(command);
                writer.Flush();
                // 如果是查询命令，接收响应
                if (command.EndsWith("?"))
                {
                    return reader?.ReadLine();
                }
                return null;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送命令出错: {ex.Message}");
                return null;
            }
        }

        // 关闭连接
        public void Close()
        {
            try
            {
                reader?.Close();
                writer?.Close();
                stream?.Close();
                client?.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭连接出错: {ex.Message}");
            }
        }

        #region 命令

        public bool SetCurrent(double current)
        {
            string str = SendCommand(SET_CURRENT + current.ToString());
            str = SendCommand(GET_CURRENT_SET);
            if (Convert.ToDouble(str) == current)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取实际输出电流
        /// </summary>
        /// <returns></returns>
        public double GeTRealCurrent()
        {
            string curr = SendCommand(GET_CURRENT);
            if (double.TryParse(curr, out double real))
            {
                return real;
            }
            return -1;
        }

        /// <summary>
        /// 设置是否输出电流
        /// </summary>
        /// <param name="isOpen"></param>
        /// <returns>true表示设置成功，false表示设置失败</returns>
        public bool SetOutput(bool isOpen)
        {
            string str;
            if (isOpen)
            {
                str = SendCommand(OPEN_OUTPUT_CURRENT);
            }
            else
            {
                str = SendCommand(CLOSE_OUTPUT_CURRENT);
            }
            Thread.Sleep(100);
            str = SendCommand(GET_OUTPUT_STATUS);
            if (isOpen == (str == "1"))
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// 设置电源控制模式
        /// </summary>
        /// <param name="isOpen"></param>
        /// <returns>true表示设置成功，false表示设置失败</returns>
        public bool SetControlMode()
        {
            string str;
            str = SendCommand(PROCESS_CTRL);
            return false;
        }
        /// <summary>
        /// 设置电源恒流模式
        /// </summary>
        /// <param name="isOpen"></param>
        /// <returns>true表示设置成功，false表示设置失败</returns>
        public bool SetCCMode()
        {
            string str;
            str = SendCommand(CONSTANT_CURRENT);
            str = SendCommand(GET_PRIORITY_TYPE);
            if (str == "CC")
            {
                return true;
            }
            return false;
        }
        #endregion
    }
}
